package com.awesome.common.util.log;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;


/**
 * Author: JFangZ
 * Email: janezhang1901@163.com
 * Date: 2021/8/21 22:34
 * Description:
 */
public class ShowLogUtil {
    private static final String TAG = "jlog";
    private static final int LENGTH = 1024 * 2;
    private static final SimpleDateFormat sSimpleDataFormatForFile = new SimpleDateFormat("yyyy-MM-dd-HH-00-00", Locale.getDefault());
    private static final SimpleDateFormat sSimpleDataFormatForLog = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault());

    private static BufferedWriter sBufferedWriter = null;
    private static LogLevel sLogLevel = LogLevel.DEBUG;
    private static String sPath = null;
    private static Calendar sCalendar = null;

    public enum LogLevel {
        DEBUG, INFO, WARN, ERROR, NONE
    }

    /**
     * Author: JFangZ
     * Email: janezhang1901@163.com
     * Date:2021/10/22 17:55
     * Description:监听时间变化
     */
    private static final BroadcastReceiver mTimeTickBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (sCalendar == null) {
                return;
            }
            if (TextUtils.equals(intent.getAction(), Intent.ACTION_TIME_TICK)) {
                // 监听到时间变化
                Calendar currentCalendar = Calendar.getInstance();
                if (currentCalendar.get(Calendar.YEAR) != sCalendar.get(Calendar.YEAR)
                        || currentCalendar.get(Calendar.MONTH) != sCalendar.get(Calendar.MONTH)
                        || currentCalendar.get(Calendar.DAY_OF_YEAR) != sCalendar.
                        get(Calendar.DAY_OF_YEAR)
                        || currentCalendar.get(Calendar.HOUR_OF_DAY) != sCalendar.
                        get(Calendar.HOUR_OF_DAY)) {
                    try {
                        if (sBufferedWriter != null) {
                            sBufferedWriter.flush();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        if (sBufferedWriter != null) {
                            try {
                                sBufferedWriter.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            sBufferedWriter = null;
                        }
                    }
                }
            }
        }
    };

    private static String getStackTraceElement() {
        for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {
            if (!stackTraceElement.isNativeMethod()
                    && !TextUtils.equals(stackTraceElement.getClassName(), Thread.class.getName())
                    && !TextUtils.equals(stackTraceElement.getClassName(), ShowLogUtil.class.getName())) {
//                return stackTraceElement.toString();
                // Remove pkg name.
//                return stackTraceElement.toString().substring(stackTraceElement.getClassName().lastIndexOf(".") + 1);
                return "(" + stackTraceElement.getFileName() + ":" + stackTraceElement.getLineNumber() + ")";
            }
        }
        return null;
    }

    private synchronized static void createFile(Date date) {
        try {
            File file = new File(sPath + File.separator + sSimpleDataFormatForFile.format(date).toString() + ".log");
            file.getParentFile().mkdirs();
            if (!file.exists()) {
                file.createNewFile();
            }
            if (sBufferedWriter == null) {
                sCalendar = Calendar.getInstance();
                sBufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true)));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private synchronized static void writeFile(String level, String tag, String log) {
        if (sPath == null) {
            return;
        }
        Date date = new Date(System.currentTimeMillis());
        createFile(date);
        try {
            String currentTime = sSimpleDataFormatForLog.format(date);
            if (sBufferedWriter != null) {
                sBufferedWriter.write(currentTime + "\t" + level + "/" + tag + " : " + log);
                sBufferedWriter.newLine();
                sBufferedWriter.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void setLogLevel(LogLevel logLevel) {
        sLogLevel = logLevel;
    }

    public static void setPath(Context context, String path) {
        sPath = path;
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_TIME_TICK);
        context.registerReceiver(mTimeTickBroadcastReceiver, intentFilter);
    }

    public static void debug(Object log) {
        if (log == null) {
            debug(TAG, "null");
        } else {
            debug(TAG, log.toString());
        }
    }

    public static void debug(String tag, String log) {
        if (sLogLevel.ordinal() > LogLevel.DEBUG.ordinal()) {
            return;
        }
        String stackTraceElement = getStackTraceElement();
        if (stackTraceElement != null) {
            tag += stackTraceElement;
        }
        int a = log.length() / LENGTH;
        for (int i = 0; i <= a; i++) {
            String subLog;
            if (i == a) {
                subLog = log.substring(i * LENGTH);
            } else {
                subLog = log.substring(i * LENGTH, (i + 1) * LENGTH);
            }
            Log.d(tag, subLog);
            writeFile("D", tag, subLog);
        }
    }


    public static void info(Object log) {
        if (log == null) {
            info(TAG, "null");
        } else {
            info(TAG, log.toString());
        }
    }

    public static void info(String tag, String log) {
        if (sLogLevel.ordinal() > LogLevel.INFO.ordinal()) {
            return;
        }
        String stackTraceElement = getStackTraceElement();
        if (stackTraceElement != null) {
            tag += stackTraceElement;
        }
        int a = log.length() / LENGTH;
        for (int i = 0; i <= a; i++) {
            String subLog;
            if (i == a) {
                subLog = log.substring(i * LENGTH);
            } else {
                subLog = log.substring(i * LENGTH, (i + 1) * LENGTH);
            }
            Log.i(tag, subLog);
            writeFile("I", tag, subLog);
        }
    }

    public static void warn(Object log) {
        if (log == null) {
            warn(TAG, "null");
        } else {
            warn(TAG, log.toString());
        }
    }

    public static void warn(String tag, String log) {
        if (sLogLevel.ordinal() > LogLevel.WARN.ordinal()) {
            return;
        }
        String stackTraceElement = getStackTraceElement();
        if (stackTraceElement != null) {
            tag += stackTraceElement;
        }
        int a = log.length() / LENGTH;
        for (int i = 0; i <= a; i++) {
            String subLog;
            if (i == a) {
                subLog = log.substring(i * LENGTH);
            } else {
                subLog = log.substring(i * LENGTH, (i + 1) * LENGTH);
            }
            Log.w(tag, subLog);
            writeFile("W", tag, subLog);
        }
    }

    public static void error(Object log) {
        if (log == null) {
            error(TAG, "null");
        } else {
            error(TAG, log.toString());
        }
    }

    public static void error(String tag, String log) {
        if (sLogLevel.ordinal() > LogLevel.ERROR.ordinal()) {
            return;
        }
        String stackTraceElement = getStackTraceElement();
        if (stackTraceElement != null) {
            tag += stackTraceElement;
        }
        int a = log.length() / LENGTH;
        for (int i = 0; i <= a; i++) {
            String subLog;
            if (i == a) {
                subLog = log.substring(i * LENGTH);
            } else {
                subLog = log.substring(i * LENGTH, (i + 1) * LENGTH);
            }
            Log.e(tag, subLog);
            writeFile("E", tag, subLog);
        }
    }
}